C++/WinRT ARM64

Here we will setup dev env and build blank Universal Windows Platform (UWP) app for WinRT/ARM64. In Visual Studio 2019 for C++/WinRT you have only five project templates: 1) Console Application; 2) Windows Runtime Component; 3) Blank App; 4) Core App; 5) Desktop Application. Core App skeleton is a bit heavy and Runtime Component is not runnable let's show How to build the latest blank UWP application for ARM64.

It's been a time since Windows RT was introduced as hardware, where for some reason custom Win32 apps were blocked to run. Now with the introduction of XAML Islands, there is an ability to compile not only truly native and compact C++ WinRT, but also legacy Win32 applications. In this article, I want to show in details the very basic parts of modern Windows 10 application built with C++ and most modern API WinRT for most modern platform ARM64. While not so many devices yet presented on the market everyone already feels the potential of ARM64 architecture. And as was reported Lumia 950 devices are able to run full-featured Windows 10 Pro for ARM64 in dual boot mode. And we have some pad and evaluation boards include Raspberry Pi B+. So there is already some room for playing with ARM64 today.

PATH

For console build, you need properly specified paths to both Windows Kit and Visual Studio folders. I'm doing this every time I install Windows dev box, unfortunately, we are still far from zero dev env creation in 2019 at all platforms. So take these paths when you prefer to control everything:

— C:\Windows\Microsoft.NET\Framework64\v4.0.30319
— C:\Program Files (x86)\Windows Kits\10\bin\10.0.18362.0\x64
— C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.8 Tools\x64

The Visuall Studio folder are placed here "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community", so add the following relative paths from here:

— VC\Tools\MSVC\14.20.27508\bin\Hostx64\x64
— MSBuild\Microsoft\VC\v160
— MSBuild\Current\Bin

INCLUDES

The language projection or rather bunch of include files is being generated by cppwinrt tool which is now a part of xlang, but delivered through nuget channel. The cppwinrt reads platform.winmd and windows.winmd metainformation, and generates winrt/base.h file along with the whole WinRT API that includes all legacy pointer conversions. The best way to learn WinRT namespaces is by using .NET CLR tool ildasm as WinRT metainformation is compatible with .NET and this is defined in ECMA-335. I assume you're going the easy way and have used Visual Studio 2019 for this code generation. But if you're willing to do this by yourself here is how:

cppwinrt.exe -base -input 10.0.18362.0 -include winrt -output "Generated Files"

NOTE: The latest cppwinrt binary for your host platform can be obtained with pwsh and 'Install-Package Microsoft.Windows.CppWinRT' or with 'nuget install Microsoft.Windows.CppWinRT'.

The game changer here the fact than Microsoft is dropping all the legacy APIs like MFC, ATL, WTL. Mostly these libraries were marshalling pointers and data across COM linkage boundaries. Now all that work is done in compile time thanks to Kenny Kerr. The code generated by cppwinrt is also clean and STL compatible, which enables zero dependency standard C++ programming as native approach in Windows, something we all were dreaming on.

microsoft/xlang

PE/COFF

Here is covered binary image generation. You can specify the build targets by msbuild arguments:

msbuild /p:Configuration=Release /p:Platform=ARM64 /p:PlatformToolset=v142 /p:TargetPlatformVersion=10.0.18362.0 /p:PreferredToolArchitecture=ARM64

The msbuild tool is being distributed over Windows/Microsoft.NET, Windows Kit and Visual Studio channels. It is also available at nuget and github:

microsoft/msbuild

If you want to build PE/COFF manually, here are command line options. Please ensure you're using right binary from your host folder 'VC/Tools/MSVC/14.20.27508/bin/Hostx64/ARM64' when you do cross compilation. Here is example of direct cl invokation for Hostx64/ARM64.

set ide="C:\Program Files (x86)\Microsoft Visual Studio\2019\Community" set ref=%ide%\VC\Tools\MSVC\14.20.27508\lib\x86\store\references set inc=%ide%\VC\Tools\MSVC\14.20.27508\include cl pch.cpp App.cpp MainPage.cpp ^ "Generated Files\XamlTypeInfo.g.cpp" "Generated Files\XamlTypeInfo.Impl.g.cpp" ^ "Generated Files\XamlMetaDataProvider.cpp" "Generated Files\module.g.cpp" ^ /c /ZW:nostdlib /EHs /GS /GL /sdl /O2 /Os /bigobj /await ^ /fp:precise /Zc:wchar_t /Zc:forScope /W4 /std:c++17 ^ /D NDEBUG /D _UNICODE /D UNICODE /D WINAPI_FAMILY=WINAPI_FAMILY_APP ^ /AI"C:\Program Files (x86)\Windows Kits\10\UnionMetadata\10.0.18362.0" ^ /AI%ref% /I".\\" /I"Generated Files\\" /I%inc% ^ /I"C:\Program Files (x86)\Windows Kits\10\Include\10.0.18362.0\um" ^ /I"C:\Program Files (x86)/Windows Kits/10/Include/10.0.18362.0/shared" ^ /I"C:\Program Files (x86)/Windows Kits/10/Include/10.0.18362.0/winrt" ^ /I"C:\Program Files (x86)/Windows Kits/10/Include/10.0.18362.0/ucrt"

Here is link part:

link pch.obj App.obj MainPage.obj module.g.obj XamlMetaDataProvider.obj ^ XamlTypeInfo.Impl.g.obj XamlTypeInfo.g.obj WindowsApp.lib ^ /LIBPATH:"C:\Program Files (x86)\Windows Kits\10\Lib\10.0.18362.0\um\arm64" ^ /LIBPATH:"C:\Program Files (x86)\Windows Kits\10\Lib\10.0.18362.0\ucrt\arm64" ^ /LIBPATH:%ide%\VC\Tools\MSVC\14.20.27508\lib\arm64 ^ /DYNAMICBASE /SUBSYSTEM:WINDOWS /MACHINE:ARM64 /APPCONTAINER ^ /OPT:REF /LTCG /OPT:ICF /NXCOMPAT /TLBID:1 /OUT:ARM64/Release/Chat/Chat.exe

The PE/COFF Chat.exe application takes 187KB on x64 and 182KB on ARM64. You can inspect dependencies with dumpbin tool:

dumpbin /imports ARM64/Release/Chat/Chat.exe | find ".dll"

You may also want to use other tools as well, not all of them however correctly handle the ARM64 binaries, among tools that do is the free (but not open source) PE File Browser which you could find useful for dependencies tracking (here is example that shows wrong PowerShell winrt module placement and missing DLL in dependencies).

If you're hacker wannabe and prefer text mode please consider using the iconic hacking tool from DOS ages HIEW32 by SEN. This tool not only provides excessive header and import dumps, but also contains powerful disassembler (and assembler!) with symbols support, built-in language for cyphering data and public API for plugins. Real hacker's tool for binary investigation. If you need more power then only IDA could help you.

By using these tools we are ensuring that Chat.exe depends only on api-ms-win-crt, api-ms-win-core, KERNEL32, OLE32, OLEAUT32, VCRUNTIME140_APP modules, which makes it technically just a Win32/COM application with .NET metainformation.

APPX

Issue self-signed certificate.

MakeCert -eku "1.3.6.1.5.5.7.3.3,1.3.6.1.4.1.311.10.3.13" -n "CN=SYNRC" ^ -r -h 0 -a sha256 -e 11/26/2100 -sv wt.pvk wt.cer

Please mind that 'CN=SYNRC' publisher's name should be the same as in AppxManifest.xml files of the application.

<Identity Name="9dc87628-26b5-45ad-94ca-281fcff0b6a7" Publisher="CN=SYNRC" Version="0.9.0.0" ProcessorArchitecture="arm64" />

Convert it to Microsoft PFX:

Pvk2Pfx /pvk wt.pvk /spc wt.cer /pfx wt.pfx

After building the binaries you're unable to run the application immediately, first you need to create .appx file with makeappx which is a part of Windows Kit:

MakeAppX pack /d "./ARM64/Release/Chat/" /l /p "./Chat.appx"

And as you guess that's not enough as you need to sign your application client certificate with $100 of cost enrollment from Microsoft. NOTE: SHA256 is the only way.

SignTool sign /fd SHA256 /a /f Chat.pfx Chat.appx

Now you're able to deploy and run app from start menu or send the app to store for review.

Make this page better: https://github.com/5ht/tonpa.guru/issues/9